import { Spriteset } from "@/containers/Spriteset.js";
import { Sprite } from "@/sprites/Sprite.js";
import { Sprite_Tiling } from "@/sprites/Sprite_Tiling.js";
import { Sprite_Character } from "@/sprites/Sprite_Character.js";
import { MapContainer } from "@/containers/MapContainer.js";
import { Sprite_Destination } from "@/sprites/Sprite_Destination.js";
import { Weather } from "@/containers/Weather.js";
import { config } from "@/managers/ConfigManager.js";

import { ImageManager } from "@/managers/ImageManager.js";

export class Spriteset_Map extends Spriteset {
    constructor() {
        super();
        this.parallaxName = '';
        this.parallax = null;

        this.map = null;
        this.createParallax();
        this.createMap();
        this.createCharacters();
        this.createShadow();
        this.createWeather();
        this.createDestination();
        this.attachHandler();
    }

    destroy(opts){
        this.deattachHanlder();
        super.destroy(opts);
    }

    createParallax() {
        this.parallax = new Sprite_Tiling();
        this.parallax.move(0, 0);
        this.parallax.setSize(config.width, config.height);
        this.base.addChild(this.parallax);
        this.loadParallaxSource();
    }
    createMap() {
        this.map = new MapContainer();

        this.map.tileWidth = $gameMap.tileWidth();
        this.map.tileHeight = $gameMap.tileHeight();
        this.map.setData($gameMap.width(), $gameMap.height(), $gameMap.data());
        this.map.horizontalWrap = $gameMap.isLoopHorizontal();
        this.map.verticalWrap = $gameMap.isLoopVertical();
        this.map.loadTileset();
        this.base.addChild(this.map);
    }

    createCharacters() {
        this.characters = [];
        let f = v => {
            let sprite = new Sprite_Character(v);
            this.characters.push(sprite);
            this.map.addChild(sprite);
        }
        $gameMap.events().forEach(f);
        $gameMap.vehicles().forEach(f);
        $gamePlayer.followers().reverseEach(f);
        f($gamePlayer);
    }

    createShadow() {
        ImageManager.loadSystem('Shadow1').then(source => {
            this.shadow = new Sprite(source);
            this.shadow.anchor.set(0.5, 1);
            this.shadow.zIndex = 6;
            this.map.addChild(this.shadow);
        });
    }

    createDestination() {
        this.destination = new Sprite_Destination(48,48);
        this.destination.zIndex = 9;
        this.map.addChild(this.destination);
    }

    createWeather() {
        this.weather = new Weather();
        this.addChild(this.weather);
    }

    attachHandler(){
        $gameMap.on('map:parallax',this.onParallaxEvents);
        let airship=$gameMap.airship();
        airship.on('vehicle',this.onShadowEvents);
        airship.on('character:bus',this.onShadowEvents);
    }

    deattachHanlder(){
        $gameMap.off('map:parallax',this.onParallaxEvents);
        let airship=$gameMap.airship();
        airship.off('vehicle',this.onShadowEvents);
        airship.on('character:bus',this.onShadowEvents);
    }

    onParallaxEvents=(type)=>{
        switch(type){
            case 'name':
                this.loadParallaxSource();
                break;
            case 'position':
                this.updateParallaxPosition();
                break;
        }
    }

    onShadowEvents=(type)=>{
        switch(type){
            case 'altitude':
                this.shadow.alpha=$gameMap.airship().shadowOpacity() / 255
                break;
            case 'move':
            case 'jump':
                let airship = $gameMap.airship();
                this.shadow.x = airship.shadowX();
                this.shadow.y = airship.shadowY();
                break;
        }
    }

    updateParallaxPosition() {
        if (this.hasParallax()) {
            this.parallax.tilePosition.x= $gameMap.parallaxOx();
            this.parallax.tilePosition.y=$gameMap.parallaxOy();
        }
    }

    updateDestination(){
        if ($gameTemp.isDestinationValid()){
            this.destination.activate();
            this.destination.setDestination(
                $gameMap.adjustX($gameTemp.destinationX()),
                $gameMap.adjustY($gameTemp.destinationY())
            );
        }else{
            this.destination.deactivate();
        }
    }

    loadParallaxSource=()=>{
        let parallaxName = $gameMap.parallaxName();
        if(parallaxName){
            ImageManager.loadParallax(this.parallaxName).then(source => {
                this.parallax.source = source;
                this.parallax.visible=true;
            });
        }else{
            this.parallax.visible=false;
        }
    }

    hasParallax(){
        return $gameMap.parallaxName();
    }
}